package 哈夫曼树编码实验;


import java.io.*;
import java.util.*;

public class test {
    public static void main(String[] args) {

        //读取文档中的英文文档
        String[] a = new String[800];
        try (FileReader reader = new FileReader("英文文档");
             BufferedReader br = new BufferedReader(reader)
        ) {
            int b =0;
            for (int i =0;i<800;i++){
                a[b]=br.readLine();
                b++;
            }
            } catch (IOException e) {
            e.printStackTrace();
        }
        String[] b = a[0].split("");
    //    System.out.println(Arrays.toString(b));
//开始构造哈夫曼树
        int an=0;
        int bn=0;
        int cn=0;
        int dn=0;
        int en=0;
        int fn=0;
        int gn=0;
        int hn=0;
        int in=0;
        int jn=0;
        int kn=0;
        int ln=0;
        int mn=0;
        int nn=0;
        int on=0;
        int pn=0;
        int qn=0;
        int rn=0;
        int sn=0;
        int tn=0;
        int un=0;
        int vn=0;
        int wn=0;
        int xn=0;
        int yn=0;
        int zn=0;
        int zkongge=0;
        for (int i =0;i<b.length;i++){
            if (b[i].equals("a")){
                an++;
                }
            if (b[i].equals("b")){
                bn++;
            }
            if (b[i].equals("c")){
                cn++;
            }
            if (b[i].equals("d")){
                dn++;
            }
            if (b[i].equals("e")){
                en++;
            }
            if (b[i].equals("f") ){
                fn++;
            }
            if (b[i].equals("g")){
                gn++;
            }
            if (b[i].equals("h")){
                hn++;
            }
            if (b[i].equals("i")){
                in++;
            }
            if (b[i].equals("j")){
                jn++;
            }
            if (b[i].equals("k")){
                kn++;
            }
            if (b[i].equals("l")){
                ln++;
            }
            if (b[i].equals("m")){
                mn++;
            }
            if (b[i].equals("n")){
                nn++;

            }
            if (b[i].equals("o")){
                on++;
            }
            if (b[i].equals("p")){
                pn++;
            }
            if (b[i].equals("q")){
                qn++;
            }
            if (b[i].equals("r")){
                rn++;
            }
            if (b[i].equals("s")){
                sn++;
            }
            if (b[i].equals("t")){
                tn++;
            }
            if (b[i].equals("u")){
                un++;
            }
            if (b[i].equals("v")){
                vn++;
                }
            if (b[i].equals("w")){
                wn++;
            }
            if (b[i].equals("x")){
                xn++;
            }
            if (b[i].equals("y")){
                yn++;
            }
            if (b[i].equals("z")){
                zn++;
            }
            if (b[i].equals(" "))
            {
                zkongge++;
            }
        }

        Objects Za= new Objects("a",an);
        Objects Zb = new Objects("b",bn);
        Objects Zc = new Objects("c",cn);
        Objects Zd = new Objects("d",dn);
        Objects Ze = new Objects("e",en);
        Objects Zf = new Objects("f",fn);
        Objects Zg = new Objects("g",gn);
        Objects Zh = new Objects("h",hn);
        Objects Zi = new Objects("i",in);
        Objects Zj = new Objects("j",jn);
        Objects Zk = new Objects("k",kn);
        Objects Zl = new Objects("l",ln);
        Objects Zm = new Objects("m",mn);
        Objects Zn = new Objects("n",nn);
        Objects Zo = new Objects("o",on);
        Objects Zp = new Objects("p",pn);
        Objects Zq = new Objects("q",qn);
        Objects Zr = new Objects("r",rn);
        Objects Zs = new Objects("s",sn);
        Objects Zt = new Objects("t",tn);
        Objects Zu = new Objects("u",un);
        Objects Zv = new Objects("v",vn);
        Objects Zw = new Objects("w",wn);
        Objects Zx = new Objects("x",xn);
        Objects Zy = new Objects("y",yn);
        Objects Zz = new Objects("z",zn);
        Objects Zkongge = new Objects(" ",zkongge);

        System.out.println("各个字符的概率统计为：");
        Objects[] temp = new Objects[]{Za,Zb,Zc,Zd,Ze,Zf,Zg,Zh,Zi,Zj,Zk,Zl,Zm,Zn,Zo,Zp,Zq,Zr,Zs,Zt,Zu,Zv,Zw,Zx,Zy,Zz,Zkongge};
            for (int i =0;i<temp.length;i++){
                System.out.println(temp[i].getName()+"的概率为"+temp[i].getWeight()/323);
            }

        List tempp = new ArrayList();
        for (int i =0;i<temp.length;i++){
            tempp.add(temp[i]);
        }
        Collections.sort(tempp);


        while (tempp.size() > 1) {
            Collections.sort(tempp);
            Objects left = (Objects) tempp.get(0);
            left.setDate( "0");
            Objects right = (Objects) tempp.get(1);
            right.setDate( "1");
            Objects parent = new Objects(left.getName()+right.getName(), left.getWeight() + right.getWeight());
            parent.setLeft(left);
            parent.setRight(right);
            tempp.remove(left);
            tempp.remove(right);
            tempp.add(parent);
            }


            //开始进行哈夫曼编码
            Objects root = (Objects) tempp.get(0);

        System.out.println( );
        List list = new ArrayList();
        Queue queue = new ArrayDeque();
        queue.offer(root);
        while (!queue.isEmpty()){
            list.add(queue.peek());
            Objects temp1 = (Objects) queue.poll();

            if(temp1.getLeft() != null)
            {
                queue.offer(temp1.getLeft());
                temp1.getLeft().setDate(temp1.getDate()+"0");

            }

            if(temp1.getLeft() != null)
            {
                queue.offer(temp1.getRight());
                temp1.getRight().setDate(temp1.getDate()+"1");
            }
        }


        System.out.println(Arrays.toString(temp));
        System.out.println();

        //进行加密
        String result = "";
        for (int i =0 ;i<b.length;i++){
            for (int j=0;j<temp.length;j++){
                if (b[i].equals(temp[j].getName())){
                    result+=temp[j].getDate();
                    break;
                }

            }
        }
        System.out.println("加密后");
        System.out.println(result);
        File file = new File("加密后文档");
        FileWriter fileWritter = null;
        try {
            fileWritter = new FileWriter(file.getName(),true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fileWritter.write(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fileWritter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //解密，读取需要解密的文档
        try (FileReader reader = new FileReader("加密后文档");
             BufferedReader br = new BufferedReader(reader)
        ) {
            int e =0;
            for (int i =0;i<800;i++){
                a[e]=br.readLine();
                e++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        String duqu=a[0];
        String jiemi="";
        String temp2="";

        for (int i =0;i<duqu.length();i++){
            temp2+=duqu.charAt(i);
            for (int j = 0;j<temp.length;j++){
                if (temp2.equals(temp[j].getDate())){
                    jiemi+=temp[j].getName();
                    temp2="";
                }
            }
        }
        System.out.println("解密后");
        System.out.println(jiemi);
        //将解密后的文本写入文件

        File file1 = new File("解密后文档");
        FileWriter fileWritter1 = null;
        try {
            fileWritter1 = new FileWriter(file1.getName(),true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fileWritter1.write(jiemi);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fileWritter1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }




    }




}
